import os
import sys
import urllib.request
import configparser
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import logging


def init_log():
    """初始化日志

    增加日志相关配置, 写入文件, 且防止出现中文乱码
    """
    file = open("error.log", encoding="utf-8", mode="a")
    logging.basicConfig(level=logging.ERROR,
                        stream=file,
                        format="%(asctime)s "
                        "%(filename)s [line:%(lineno)d] "
                        "%(levelname)s: "
                        "%(message)s",
                        datefmt="%a, %d %b %Y %H:%M:%S")


def handle_exception(exc_type, exc_value, exc_traceback):
    print(exc_value)
    os.system('pause')
    sys.exit(1)


def load_config():
    """读取配置文件

    从当前目录下读取config.ini文件

    Returns:
        config: 配置对象

    """
    assert os.path.isfile('config.ini'), '配置文件不存在'
    config = configparser.ConfigParser()
    config.read('config.ini', encoding='utf-8')
    return config.get('database', 'url'),\
            config.get('database', 'table'),\
            config.get('database','column'),\
            config.get('file', 'base_url')


def connect_database(database_url):
    """链接数据库
    
    根据配置文件链接数据库, 创建会话

    Returns:
        Session(): 创建新的会话
    """
    engine = create_engine(database_url)
    Session = sessionmaker(bind=engine)
    return Session()


def get_files(database_url, table, column):
    session = connect_database(database_url)
    return [one[0] for one in session.execute("select %s from %s where %s is not null" % (column, table, column)).fetchall()]


def download_file(base_url, file_name):
    # os.path.join会从第一个分隔符开始拼接, 防止出现路径拼接错误, 去除下载文件相对路径开头的分隔符
    if file_name[0] == "/" or file_name[0] == "\\":
        file_name = file_name[1:]
    # 拼接图片路径
    file_url = base_url + file_name
    print("下载文件: %s" % file_url)
    # 切换路径分隔符为当前系统的分隔符
    save_path_name = os.path.join(os.getcwd(), file_name.replace(r'\/'.replace(os.sep, ''), os.sep))
    save_path = save_path_name.rsplit(os.sep, 1)[0]
    # 检查路径
    if not os.path.exists(save_path):
        os.makedirs(save_path)
    try:
        urllib.request.urlretrieve(file_url, save_path_name)
        return True
    except Exception as e:
        logging.error("下载失败, 文件路径为: %s" % file_url)
        return False


if __name__ == "__main__":
    # 手动输入, 暂时不用
    # base_url, database_url, table, column = ''
    # custom = input('是否手动输入?(y/n):')
    # if custom in ['y', 'yes']:
    #     base_url = input('服务器访问域名(必须以/结尾):')
    #     database_url = input('数据库url:')
    #     table = input('表名:')
    #     column = input('列名:')
    sys.excepthook = handle_exception
    init_log()
    print('读取配置文件...')
    database_url, table, column, base_url = load_config()
    print('查询下载文件列表...')
    try:
        files = get_files(database_url, table, column)
    except Exception as e:
        raise Exception('数据库查询失败, 请检查相关配置')
    has_error = False
    for file in files:
        if not download_file(base_url, file):
            has_error = True
    if has_error:
        print('有文件下载失败, 详情查看日志文件')
    os.system('pause')